﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using PmSoft.Core;
using PmSoft.Web.Abstractions.Authorization;

namespace PmSoft.Web.Abstractions.Middlewares;

/// <summary>
/// 自定义中间件，用于拦截并处理未经授权（401）和禁止访问（403）的 HTTP 响应。
/// 将默认的空响应替换为统一的 JSON 格式响应，提供更友好的错误信息。
/// </summary>
public class CustomUnauthorizedMiddleware
{
	private readonly RequestDelegate _next;

	/// <summary>
	/// 初始化 CustomUnauthorizedMiddleware 的新实例。
	/// </summary>
	/// <param name="next">请求管道中的下一个委托，用于继续处理请求。</param>
	public CustomUnauthorizedMiddleware(RequestDelegate next)
	{
		_next = next;
	}

	/// <summary>
	/// 异步执行中间件逻辑，检查响应状态码并处理 401 和 403 状态。
	/// </summary>
	/// <param name="context">HTTP 上下文，包含请求和响应的信息。</param>
	/// <returns>异步任务，表示中间件处理已完成。</returns>
	public async Task InvokeAsync(HttpContext context)
	{
		// 执行管道中的下一个中间件
		await _next(context);

		if (context.Items.TryGetValue("AuthFailure", out var failureObj) && failureObj is AuthFailureInfo failure)

		{
			context.Response.StatusCode = failure.StatusCode;
			context.Response.ContentType = "application/json";
			await context.Response.WriteAsync(Json.Stringify(ApiResult.Error(failure.Code, failure.Message)));
		}
		else
		// 检查响应状态码
		if (!context.Response.HasStarted && context.Response.StatusCode == StatusCodes.Status401Unauthorized)
		{
			await HandleUnauthorizedAsync(context);
		}
		else if (!context.Response.HasStarted && context.Response.StatusCode == StatusCodes.Status403Forbidden)
		{
			await HandleForbiddenAsync(context);
		}
	}

	/// <summary>
	/// 处理未授权（401）响应，返回自定义的 JSON 格式错误信息。
	/// </summary>
	/// <param name="context">HTTP 上下文，用于设置响应内容。</param>
	/// <returns>异步任务，表示响应已写入。</returns>
	private static async Task HandleUnauthorizedAsync(HttpContext context)
	{
		// 设置响应内容类型为 JSON
		context.Response.ContentType = "application/json";
		// 使用 ApiResult.Error 生成错误响应并序列化为 JSON
		await context.Response.WriteAsync(Json.Stringify(ApiResult.Error("UNAUTHENTICATED", "身份验证失败，请提供有效的凭据")));
	}

	/// <summary>
	/// 处理禁止访问（403）响应，返回自定义的 JSON 格式错误信息。
	/// </summary>
	/// <param name="context">HTTP 上下文，用于设置响应内容。</param>
	/// <returns>异步任务，表示响应已写入。</returns>
	private static async Task HandleForbiddenAsync(HttpContext context)
	{
		// 设置响应内容类型为 JSON
		context.Response.ContentType = "application/json";
		// 使用 ApiResult.Error 生成错误响应并序列化为 JSON
		await context.Response.WriteAsync(Json.Stringify(ApiResult.Error("FORBIDDEN", "您没有访问此资源的权限")));
	}
}

/// <summary>
/// 提供扩展方法，用于在应用程序管道中注册 CustomUnauthorizedMiddleware。
/// </summary>
public static class CustomUnauthorizedMiddlewareExtensions
{
	/// <summary>
	/// 将自定义未授权中间件添加到应用程序管道中。
	/// </summary>
	/// <param name="builder">应用程序构建器，用于配置请求管道。</param>
	/// <returns>更新后的应用程序构建器。</returns>
	public static IApplicationBuilder UseCustomUnauthorized(this IApplicationBuilder builder)
	{
		return builder.UseMiddleware<CustomUnauthorizedMiddleware>();
	}
}